package com.atomscat.lottery.service;


import com.atomscat.lottery.entity.db.RoleEntity;
import com.atomscat.lottery.entity.db.UserEntity;
import com.atomscat.lottery.entity.vo.request.CreateAdminUserRequest;
import com.atomscat.lottery.entity.vo.response.BaseResponse;
import com.atomscat.lottery.repository.RoleEntityRepository;
import com.atomscat.lottery.repository.UserEntityRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Example;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Optional;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserEntityService {

    private final UserEntityRepository userEntityRepository;
    private final RoleEntityRepository roleEntityRepository;
    private final VoBaseRespTransformService voBaseRespTransformService;

    /**
     * Find user by username
     *
     * @param username the username
     * @return the user
     */
    public UserEntity findByLoginId(String username) {
        UserEntity userEntity = new UserEntity();
        userEntity.setLoginId(username);
        Optional<UserEntity> optionalUserEntity = userEntityRepository.findOne(Example.of(userEntity));
        if (optionalUserEntity.isEmpty()) {
            return null;
        }
        return optionalUserEntity.stream().toList().get(0);
    }

    /**
     * Find user by username
     *
     * @param username the username
     * @return the user
     */
    public Mono<UserEntity> findOne(User username) {
        UserEntity userEntity = new UserEntity();
        userEntity.setLoginId(username.getUsername());
        Optional<UserEntity> optionalUserEntity = userEntityRepository.findOne(Example.of(userEntity));
        userEntity = optionalUserEntity.orElse(null);
        if (userEntity != null) {
            List<RoleEntity> roles = userEntity.getRoles();
            log.debug("User found with username: {}", username);
            return Mono.just(userEntity);
        }
        log.debug("User not found with username: {}", username);
        return Mono.empty();
    }

    /**
     * Find user by username
     *
     * @param username the username
     * @return the user
     */
    public Optional<User> findByUsername(String username) {
        UserEntity userEntity = findByLoginId(username);
        if (userEntity != null) {
            List<RoleEntity> roles = userEntity.getRoles();
            log.debug("User found with username: {}", username);
            return Optional.of(new User(userEntity.getLoginId(), userEntity.getPassword(), roles.stream().map(roleEntity -> new SimpleGrantedAuthority(roleEntity.getRoleCode())).toList()));
        }
        log.debug("User not found with username: {}", username);
        return Optional.empty();
    }


    // add create admin user method
    public BaseResponse<Long> createAdminUser(CreateAdminUserRequest adminUserRequest) {
        UserEntity userEntity = new UserEntity();
        userEntity.setLoginId(adminUserRequest.getUsername());
        PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        userEntity.setPassword(passwordEncoder.encode(adminUserRequest.getPassword()));
        userEntity.setTitle(adminUserRequest.getTitle());
        userEntity.setFirstName(adminUserRequest.getFirstName());
        userEntity.setLastName(adminUserRequest.getLastName());
        userEntity.setRoles(roleEntityRepository.queryByIdIn(adminUserRequest.getRolesIds()));
        userEntityRepository.save(userEntity);
        return voBaseRespTransformService.transformSuccessful(userEntity.getId());
    }

    public BaseResponse<List<UserEntity>> searchUserByFirstName(String firstName) {
        UserEntity userEntity = new UserEntity();
        userEntity.setFirstName(firstName);
        List<UserEntity> userEntities = userEntityRepository.findAll(Example.of(userEntity));
        return voBaseRespTransformService.transformSuccessful(userEntities.stream().filter(entity -> {
            entity.setPassword("");
            return true;
        }).toList());
    }
}